package com.ruoyi.store.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.core.page.PagePlus;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.store.bo.*;
import com.ruoyi.store.service.IHmSystemAttachmentService;
import com.ruoyi.store.service.IHmSystemFormTempService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.store.domain.HmSystemConfig;
import com.ruoyi.store.mapper.HmSystemConfigMapper;
import com.ruoyi.store.vo.HmSystemConfigVo;
import com.ruoyi.store.service.IHmSystemConfigService;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商城配置Service业务层处理
 *
 * @author ruoyi
 * @date 2021-07-04
 */
@Service
public class HmSystemConfigServiceImpl extends ServicePlusImpl<HmSystemConfigMapper, HmSystemConfig> implements IHmSystemConfigService {

	@Resource
	private HmSystemConfigMapper dao;

	@Value("${server.asyncConfig}")
	private Boolean asyncConfig;

	@Autowired
	private RedisCache redisCache;

	@Autowired
	private IHmSystemFormTempService systemFormTempService;

	@Autowired
	private IHmSystemAttachmentService systemAttachmentService;

	private static final String redisKey = Constants.CONFIG_LIST;

	@Override
	public HmSystemConfigVo queryById(Integer id){
		return getVoById(id, HmSystemConfigVo.class);
	}

	@Override
	public TableDataInfo<HmSystemConfigVo> queryPageList(HmSystemConfigQueryBo bo) {
		PagePlus<HmSystemConfig, HmSystemConfigVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), HmSystemConfigVo.class);
		return PageUtils.buildDataInfo(result);
	}

	@Override
	public List<HmSystemConfigVo> queryList(HmSystemConfigQueryBo bo) {
		return listVo(buildQueryWrapper(bo), HmSystemConfigVo.class);
	}

	private LambdaQueryWrapper<HmSystemConfig> buildQueryWrapper(HmSystemConfigQueryBo bo) {
		Map<String, Object> params = bo.getParams();
		LambdaQueryWrapper<HmSystemConfig> lqw = Wrappers.lambdaQuery();
		lqw.like(StrUtil.isNotBlank(bo.getName()), HmSystemConfig::getName, bo.getName());
		lqw.eq(StrUtil.isNotBlank(bo.getTitle()), HmSystemConfig::getTitle, bo.getTitle());
		lqw.eq(bo.getFormId() != null, HmSystemConfig::getFormId, bo.getFormId());
		lqw.eq(StrUtil.isNotBlank(bo.getValue()), HmSystemConfig::getValue, bo.getValue());
		lqw.eq(bo.getStatus() != null, HmSystemConfig::getStatus, bo.getStatus());
		return lqw;
	}

	@Override
	public Boolean insertByAddBo(HmSystemConfigAddBo bo) {
		HmSystemConfig add = BeanUtil.toBean(bo, HmSystemConfig.class);
		validEntityBeforeSave(add);
		return save(add);
	}

	@Override
	public Boolean updateByEditBo(HmSystemConfigEditBo bo) {
		HmSystemConfig update = BeanUtil.toBean(bo, HmSystemConfig.class);
		validEntityBeforeSave(update);
		return updateById(update);
	}

	/**
	 * 保存前的数据校验
	 *
	 * @param entity 实体类数据
	 */
	private void validEntityBeforeSave(HmSystemConfig entity){
		//TODO 做一些数据校验,如唯一约束
	}

	@Override
	public Boolean deleteWithValidByIds(Collection<Integer> ids, Boolean isValid) {
		if(isValid){
			//TODO 做一些业务上的校验,判断是否需要校验
		}
		return removeByIds(ids);
	}
	/**
	 * 根据menu name 获取 value
	 * @param name menu name
	 * @author Mr.Zhang
	 * @since 2020-04-16
	 * @return String
	 */
	@Override
	public String getValueByKey(String name) {
		return get(name);
	}
	/**
	 * 把数据同步到redis
	 * @param name String
	 * @author Mr.Zhang
	 * @since 2020-04-16
	 * @return String
	 */
	private String get(String name){
		if (!asyncConfig) {
			//如果配置没有开启
			LambdaQueryWrapper<HmSystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
			lambdaQueryWrapper.eq(HmSystemConfig::getStatus, 0).eq(HmSystemConfig::getName, name);
			HmSystemConfig systemConfig = dao.selectOne(lambdaQueryWrapper);
			if(null == systemConfig || StringUtils.isBlank(systemConfig.getValue())){
				return null;
			}

			return systemConfig.getValue();

		}
		setRedisByVoList();
		Object data = redisCache.getCacheMapValue(redisKey, name);
		if(null == data || StringUtils.isBlank(data.toString())){
			//没有找到数据
			return null;
		}

		//去数据库查找，然后写入redis
		return data.toString();
	}
	/**
	 * 把数据同步到redis, 此方法适用于redis为空的时候进行一次批量输入
	 */
	private void setRedisByVoList(){
		//检测redis是否为空
		Integer size = redisCache.getHashSize(redisKey);
		if(size > 0 || !asyncConfig){
			return;
		}

		LambdaQueryWrapper<HmSystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(HmSystemConfig::getStatus, false);
		List<HmSystemConfig> systemConfigList = dao.selectList(lambdaQueryWrapper);
		async(systemConfigList);
	}
	/**
	 * 把数据同步到redis
	 * @param systemConfigList List<HmSystemConfig> 需要同步的数据
	 */
	private void async(List<HmSystemConfig> systemConfigList){
		if (!asyncConfig) {
			//如果配置没有开启
			return;
		}

		for (HmSystemConfig systemConfig : systemConfigList) {
			redisCache.setCacheMapValue(redisKey, systemConfig.getName(), systemConfig.getValue());
		}
	}

	/**
	 * 整体保存表单数据
	 * @param systemFormCheckRequest SystemFormCheckRequest 数据保存
	 * @return boolean
	 */
	@Override
	public boolean saveForm(HmSystemFormCheckBo systemFormCheckRequest) {
		//检测form表单，并且返回需要添加的数据
		systemFormTempService.checkForm(systemFormCheckRequest);

		List<HmSystemConfig> systemConfigList = new ArrayList<>();

		//批量添加
		for (HmSystemFormItemCheckBo systemFormItemCheckRequest : systemFormCheckRequest.getFields()) {
			HmSystemConfig systemConfig = new HmSystemConfig();
			systemConfig.setName(systemFormItemCheckRequest.getName());

			String value = systemAttachmentService.clearPrefix(systemFormItemCheckRequest.getValue());
			if(StringUtils.isBlank(value)){
				//去掉图片域名之后没有数据则说明当前数据就是图片域名
				value = systemFormItemCheckRequest.getValue();
			}
			systemConfig.setValue(value);
			systemConfig.setFormId(systemFormCheckRequest.getId());
			systemConfig.setTitle(systemFormItemCheckRequest.getTitle());
			systemConfigList.add(systemConfig);
		}

		//修改之前的数据
		updateStatusByFormId(systemFormCheckRequest.getId());

		saveBatch(systemConfigList);

		//删除之前隐藏的数据
		deleteStatusByFormId(systemFormCheckRequest.getId());

		List<HmSystemConfig> forAsyncPram = systemConfigList.stream().map(e -> {
			e.setStatus(true);
			return e;
		}).collect(Collectors.toList());
		async(forAsyncPram);

		return true;
	}
	/**
	 * updateStatusByGroupId
	 * @param formId Integer formId
	 */
	private void updateStatusByFormId(Integer formId){
		LambdaQueryWrapper<HmSystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(HmSystemConfig::getFormId, formId).eq(HmSystemConfig::getStatus, false);

		HmSystemConfig systemConfig = new HmSystemConfig();
		systemConfig.setStatus(true);
		update(systemConfig, lambdaQueryWrapper);

	}
	/**
	 * deleteStatusByGroupId
	 * @param formId Integer formId
	 */
	private void deleteStatusByFormId(Integer formId){
		LambdaQueryWrapper<HmSystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		//删除已经隐藏的数据
		lambdaQueryWrapper.eq(HmSystemConfig::getFormId, formId).eq(HmSystemConfig::getStatus, true);
		List<HmSystemConfig> systemConfigList = dao.selectList(lambdaQueryWrapper);
		dao.delete(lambdaQueryWrapper);
		async(systemConfigList);
	}
	/**
	 * 根据 name 获取 value 找不到抛异常
	 * @param name menu name
	 * @return String
	 */
	@Override
	public String getValueByKeyException(String name) {
		String value = get(name);
		if(null == value){
			throw new CustomException("没有找到"+ name +"数据");
		}

		return value;
	}

	/**
	 * 根据formId查询数据
	 * @param formId Integer id
	 * @author Mr.Zhang
	 * @since 2020-04-16
	 * @return HashMap<String, String>
	 */
	@Override
	public HashMap<String, String> info(Integer formId){
		LambdaQueryWrapper<HmSystemConfig> lambdaQueryWrapper1 = new LambdaQueryWrapper<>();
//        lambdaQueryWrapper1.eq(SystemConfig::getStatus, false).eq(SystemConfig::getFormId, formId);
		lambdaQueryWrapper1.eq(HmSystemConfig::getFormId, formId);
		List<HmSystemConfig> systemConfigList = dao.selectList(lambdaQueryWrapper1);
		if(systemConfigList.size() < 1){
			return null;
		}
		HashMap<String, String> map = new HashMap<>();
		for (HmSystemConfig systemConfig : systemConfigList) {
			map.put(systemConfig.getName(), systemConfig.getValue());
		}
		map.put("id", formId.toString());
		return map;
	}
}
